package com.tiancheng.onecode.aop;

import com.alibaba.fastjson.JSON;
import com.tiancheng.onecode.utils.JsonUtil;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.core.io.InputStreamSource;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.TreeMap;
import java.util.concurrent.Executor;
import java.util.stream.Collectors;


/**
 * 打印接口日志
 *
 * @author kellen
 * @date 2024/1/8
 */
@Component
@Aspect
@Slf4j
public class WebLogAspect {

    @Autowired
    @Qualifier("logExecutor")
    private Executor logExecutor;

    @Pointcut("execution(public * com.tiancheng.onecode.controller..*.*(..))")
    public void webLog() {}

    @Before("webLog()")
    public void doBefore(JoinPoint point) {
        try {
            long startTime = System.currentTimeMillis();

            // 开始打印请求日志
            HttpServletRequest request = ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes()))
                    .getRequest();


            final String requestUrl = request.getRequestURL().toString();
            final String requestMethod = request.getMethod();
            List<Object> params = Arrays.stream(point.getArgs())
                    .filter(d -> !(d instanceof InputStreamSource) && !(d instanceof ServletRequest) && !(d instanceof ServletResponse)).collect(Collectors.toList());
            String requestParameter=params.size() > 1 ?
                    JSON.toJSONString(params) : (params.size() > 0 ? JSON.toJSONString(params.get(0)) : null);
            //requestInfoMap.put("userId", null == StpUtil.getLoginId() ? "" : StpUtil.getLoginId() );

            // 健康检查不打印日志
            if (requestUrl.contains("readinessProbe")) {
                return;
            }
            long endTime = System.currentTimeMillis();
            logExecutor.execute(() -> log.info("Request url:{},耗时：【{} ms】,method:{},params:{}",requestUrl,endTime - startTime,requestMethod,requestParameter));
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
    }

    @AfterReturning(value = "webLog()", returning = "rt")
    public void doAfterReturning(JoinPoint joinPoint, Object rt) {
        try {
            String appUrl = ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes()))
                    .getRequest().getRequestURL().toString();

            // 健康检查不打印日志
            if (appUrl.contains("readinessProbe")) {
                return;
            }

            if (rt != null) {
                logExecutor.execute(() -> log.info("[" + appUrl + "] result: {}", JSON.toJSONString(rt)));
            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
    }
}
